package com.mimaxueyuan.disruptor.demo5;

import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.lmax.disruptor.BlockingWaitStrategy;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.SequenceBarrier;
import com.lmax.disruptor.SleepingWaitStrategy;
import com.lmax.disruptor.WaitStrategy;
import com.lmax.disruptor.WorkerPool;
import com.lmax.disruptor.YieldingWaitStrategy;
import com.lmax.disruptor.dsl.ProducerType;

/**
 * 
 * 
 * @author: Kevin
 * @Date:2018年6月28日
 * @Project:micrioframework
 */
public class LongEventMain4 {

	public static long startTime;

	@SuppressWarnings("unchecked")
	public static void main(String[] args) throws InterruptedException {
		// 初始化线程池-用户执行Consumer
		ExecutorService threadFactory = Executors.newCachedThreadPool();
		// 初始化EventFactory
		LongEventFactory factory = new LongEventFactory();
		// 初始化RingBuffer的大小,必须是2的指数
		int bufferSize = 1024;
		
		WaitStrategy YIELDING_WAIT = new BlockingWaitStrategy();
		// 创建RingBuffer, RingBuffer类提供了四种static create方法 -> [查看源码]
		RingBuffer<LongEvent> ringBuffer = RingBuffer.create(ProducerType.MULTI, factory, bufferSize, YIELDING_WAIT);
		
		// 通过RingBuffer创建Barrier, Barrier只有一个实现类ProcessingSequenceBarrier
		SequenceBarrier barriers = ringBuffer.newBarrier();
		
		//创建WorkerHandler (与EventHandler相同, 只是它运行在WorkPool里在WorkPool里)
		LongEventWorkeHandler[] handlers = new LongEventWorkeHandler[10];
		for(int i=0;i<10;i++) {
			handlers[i] = new LongEventWorkeHandler();
		}
		
		//创建WorkerPool,主要指定WorkerPool使用哪个RingBuffer、依赖哪个Barriers
		WorkerPool<LongEvent> workerPool = new WorkerPool<LongEvent>(ringBuffer, barriers,
                new LongEventExceptionHdanler(), handlers);
		
		// 查看当前工作进度的序列数组(处理前)
		/*System.out.println(workerPool.getWorkerSequences().length);
		Sequence[] workerSequences = workerPool.getWorkerSequences();
		int m = 0;
		for(Sequence se : workerSequences) {
			System.out.println(m++ +":"+ se.get());
		}*/
		
		// 获取一个代表工作进度的序列数组: workerPool.getWorkerSequences()
		// 将指定的门控序列添加到RingBuffer实例中。它们将安全地和原子地添加到门控序列的列表中。ringBuffer.addGatingSequences()
		// 以下的方法不执行没有任何影响（建议不要采用）
        // ringBuffer.addGatingSequences(workerPool.getWorkerSequences());
		
        workerPool.start(threadFactory);
        
		// 采用固定模式向RingBuffer中添加事件
		final LongEventProducer producer = new LongEventProducer(ringBuffer);

		// 10线程并发下的Disruptor
		ExecutorService executor1 = Executors.newCachedThreadPool();
		startTime = System.currentTimeMillis();
		for (long i = 0; i < 5; i++) {
			final long vv = i;
			executor1.submit(new Runnable() {
				public void run() {
					try {
						producer.onData(vv);
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			});
		}
		
		// 查看当前工作进度的序列数组(处理后)
		/*Thread.sleep(5000);
		System.out.println(workerPool.getWorkerSequences().length);
		workerSequences = workerPool.getWorkerSequences();
		m = 0;
		for(Sequence se : workerSequences) {
			System.out.println(m++ +":"+ se.get());
		}*/
		
	}

}
